<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2017/11/21 0021
 * Time: 下午 1:51
 */

namespace common\components\OSS;

use common\components\DataHelper;
use common\components\Errors;
use OSS\Core\OssException;
use OSS\OssClient;
use yii\helpers\Url;

class AliOSS
{
    use Errors;
    protected $config;

    protected $endpoint;

    protected $is_cname = false;

    /**
     * @var OssClient
     */
    protected static $oss_client;

    public function __construct($isCName = false)
    {
        $this->config = DataHelper::getConfig('oss')['ali'];

        if ( $isCName ) {
            $this->is_cname = true;
            $this->endpoint = $this->config['cname'];
        } else {
            $this->is_cname = false;
            $this->endpoint = $this->config['endpoint'];
        }

    }

    public static function getSourceUrl($object)
    {
        $config = DataHelper::getConfig('oss')['ali'];

        if ( $config['cname'] ) {
            $host = str_replace('http://', '', $config['cname']);
        } else {
            $host = str_replace('http://', '', $config["bucket"] . "." . $config['endpoint']);
        }

        return sprintf("http://%s/%s", trim($host, '/'), ltrim($object, "/"));
    }

    public function initOssClient()
    {
        self::$oss_client = new OssClient(
            $this->config['access_key_Id'],
            $this->config['access_key_secret'],
            $this->endpoint,
            $this->is_cname
        );

        return self::$oss_client;
    }

    public function signature($dir, $expire, $callbackUrl = '', $callbackParams = [], $maxFileSize = 1048576000)
    {
        $id= $this->config['access_key_Id'];
        $key= $this->config['access_key_secret'];
        $host = str_replace([
            'http:',
            "https:"
        ], '', $this->config['bucket'] . '.' . $this->endpoint);
        if ( DataHelper::is_SSL() ) {
            $host = 'https://' . $host;#die($host);
        } else {
            $host = 'http://' . $host;#die($host);
        }
        $expire_time = time() + $expire;
        $expire_time = DataHelper::gmtIso8601($expire_time);
        $dir = rtrim($dir, '/') . "/";
        $conditions = [[
                'content-length-range',
                0,
                $maxFileSize
            ],[
                'starts-with',
                '$key',
                $dir
            ]];

        $policy = [
            'expiration'=>$expire_time,
            'conditions'=>$conditions
        ];

        $policy = json_encode($policy);
        $base64_policy = base64_encode($policy);

        $string_to_sign = $base64_policy;
        $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $key, true));

        $response = [];

        if ( $callbackUrl ) {
            $callbackBody = [
                'callbackUrl'      => $callbackUrl,
                'callbackBody'     => 'bucket=${bucket}&object=${object}&size=${size}&mimeType=${mimeType}',
                'callbackBodyType' => "application/x-www-form-urlencoded",
            ];

            if ( $callbackParams ) {
                $callbackBody['callbackBody'] = $callbackBody['callbackBody'] . '&' . http_build_query($callbackParams);
            }

            $callbackBody = json_encode($callbackBody);
            $callbackBody = base64_encode($callbackBody);
            $response['callback'] =  $callbackBody;
        }
        $response['accessid'] = $id;
        $response['host'] = $host;
        $response['policy'] = $base64_policy;
        $response['signature'] = $signature;
        $response['expire'] = $expire_time;


        //这个参数是设置用户上传指定的前缀
        $response['dir'] = $dir;

        return $response;
    }

    public static function getObjectByUrl($url)
    {
        if ( !$url ) {
            return null;
        }
        $url = parse_url($url);
        return trim(@$url["path"], "/");
    }

    public function getObjectMeta($object)
    {
        try {
            $ret = self::$oss_client->getObjectMeta($this->config["bucket"], $object);
        } catch ( OssException $e ) {
            return false;
        }
        return $ret;
    }

    public function copyObject($fromObject, $toObject)
    {
        if ( !self::$oss_client ) {
            $this->initOssClient();
        }

        try {
            self::$oss_client->copyObject($this->config["bucket"], $fromObject, $this->config["bucket"], $toObject);
        } catch ( OssException $e ) {
            return false;
        }
        return true;
    }

    public function moveObject($fromObject, $toObject)
    {
        if ( $this->copyObject($fromObject, $toObject) && $this->delObject($fromObject) ) {
            return true;
        }
        return false;
    }

    public function delObject($object)
    {
        if ( !self::$oss_client ) {
            $this->initOssClient();
        }

        try {
            self::$oss_client->deleteObject($this->config["bucket"], $object);
        } catch ( OssException $e ) {
            $this->setError("del", $e->getMessage());
            return false;
        }
        return true;
    }
    public static function imageResize($imageUrl, $w, $h, $m = 'pad', $limit = 1, $color = 'FFFFFF')
    {
        if ( !$imageUrl ) {
            return DataHelper::getDefaultImage();
        }

        return sprintf(
            "%s?x-oss-process=image/resize,m_%s,w_%d,h_%d,limit_%d,color_%s",
            $imageUrl,
            $m,
            $w,
            $h,
            $limit,
            $color
        );
    }

    public static function videoImage($imageUrl, $w, $h, $m = 'fast')
    {
        if ( !$imageUrl ) {
            return "";
        }

        return sprintf(
            "%s?x-oss-process=video/snapshot,t_1500,f_jpg,w_%d,h_%d,m_%s",
            $imageUrl,
            $w,
            $h,
            $m
        );
    }

    public static function getImageInfo($image)
    {
        $imageInfo = file_get_contents($image . "?x-oss-process=image/info");

        if ( $imageInfo ) {
            return @json_decode($imageInfo, true);
        }

        return false;
    }

    public function getConfig($key = 'ALL')
    {
        return $key === 'ALL' ? $this->config : $this->config[$key];
    }

}